package org.zoomdev.zoom.lockfree;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.IntConsumer;
import java.util.function.Supplier;

public final class FastStringBuilder {
    // VarHandle优化内存访问
    private static final VarHandle CHAR_ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(char[].class);
    private static final int DEFAULT_INIT_CAPACITY = 512;
    private static final char[] EMPTY_CHARS = new char[0];

    // 缓冲区和状态
    private char[] value;
    private int count;
    private boolean directMode = false;
    private NativeMemoryBuffer nativeBuffer;

    // 线程局部缓存配置
    private static final ThreadLocal<char[]> threadBuffer = ThreadLocal.withInitial(() ->
            new char[ThreadLocalBuffer.STATIC_INIT_CAPACITY]);
    private static boolean threadLocalEnabled = true;

    // SIMD批次处理常量
    private static final int SIMD_BATCH_SIZE = 32;

    // 性能追踪（可选的）
    private int allocations;
    private int reallocations;

    public FastStringBuilder() {
        if (threadLocalEnabled) {
            value = threadBuffer.get();
        } else {
            value = new char[DEFAULT_INIT_CAPACITY];
        }
    }

    public FastStringBuilder(int capacity) {
        value = new char[Math.max(capacity, DEFAULT_INIT_CAPACITY)];
    }

    public static void enableThreadLocal(boolean enable) {
        threadLocalEnabled = enable;
    }

    public FastStringBuilder useDirectBuffer() {
        if (nativeBuffer == null) {
            nativeBuffer = new NativeMemoryBuffer(128);
        }
        directMode = true;
        return this;
    }

    // 核心追加方法
    public FastStringBuilder append(String str) {
        if (str == null) str = "null";
        int strLen = str.length();
        int newCount = count + strLen;

        ensureCapacity(newCount);

        if (directMode) {
            nativeBuffer.append(str);
            count = newCount;
        } else if (strLen > SIMD_BATCH_SIZE) {
            appendBatched(str, strLen);
        } else {
            str.getChars(0, strLen, value, count);
            count = newCount;
        }
        return this;
    }

    // SIMD优化批量添加
    private void appendBatched(String str, int strLen) {
        int index = count;
        int batches = strLen / SIMD_BATCH_SIZE;

        for (int i = 0; i < batches; i++) {
            int batchStart = i * SIMD_BATCH_SIZE;
            for (int j = 0; j < SIMD_BATCH_SIZE; j++) {
                CHAR_ARRAY_HANDLE.setRelease(value, index++, str.charAt(batchStart + j));
            }
        }

        // 处理剩余字符
        int remaining = strLen % SIMD_BATCH_SIZE;
        if (remaining > 0) {
            int batchStart = batches * SIMD_BATCH_SIZE;
            for (int j = 0; j < remaining; j++) {
                CHAR_ARRAY_HANDLE.setRelease(value, index++, str.charAt(batchStart + j));
            }
        }

        count = index;
    }

    public FastStringBuilder append(char c) {
        ensureCapacity(count + 1);
        CHAR_ARRAY_HANDLE.setRelease(value, count++, c);
        return this;
    }

    public FastStringBuilder append(char[] chars) {
        return append(chars, 0, chars.length);
    }

    public FastStringBuilder append(char[] chars, int offset, int len) {
        if (offset < 0 || len < 0 || offset + len > chars.length) {
            throw new IndexOutOfBoundsException();
        }

        int newCount = count + len;
        ensureCapacity(newCount);

        if (len > SIMD_BATCH_SIZE) {
            System.arraycopy(chars, offset, value, count, len);
        } else {
            for (int i = 0; i < len; i++) {
                CHAR_ARRAY_HANDLE.setRelease(value, count++, chars[offset + i]);
            }
        }
        return this;
    }

    public FastStringBuilder appendCodepoint(int codePoint) {
        if (Character.isBmpCodePoint(codePoint)) {
            return append((char) codePoint);
        } else if (Character.isValidCodePoint(codePoint)) {
            ensureCapacity(count + 2);
            CHAR_ARRAY_HANDLE.setRelease(value, count++, Character.highSurrogate(codePoint));
            CHAR_ARRAY_HANDLE.setRelease(value, count++, Character.lowSurrogate(codePoint));
        } else {
            throw new IllegalArgumentException("Invalid code point: " + codePoint);
        }
        return this;
    }

    public void setLength(int newLength) {
        if (newLength < 0) throw new IndexOutOfBoundsException();

        if (newLength < count) {
            count = newLength;
            // 优化：不清空数据，下次复用
        } else if (newLength > count) {
            ensureCapacity(newLength);
            // 快速填充空白 (SIMD优化)
            for (int i = count; i < newLength; i += 8) {
                int batch = Math.min(8, newLength - i);
                for (int j = 0; j < batch; j++) {
                    CHAR_ARRAY_HANDLE.setRelease(value, count + j, ' ');
                }
                count += batch;
            }
        }
    }

    public void reset() {
        if (count > 0) {
            // 使用ThreadLocal时避免数组过大
            if (value.length > ThreadLocalBuffer.STATIC_INIT_CAPACITY * 16) {
                if (threadLocalEnabled) {
                    ThreadLocalBuffer.release(value);
                    value = threadBuffer.get();
                } else {
                    value = new char[DEFAULT_INIT_CAPACITY];
                }
            }
            count = 0;
        }
    }

    public String toString() {
        if (directMode) {
            return nativeBuffer.toString();
        }
        return new String(value, 0, count);
    }

    // 零拷贝转换 (使用String内部优化)
    public String build() {
        if (count == 0) return "";

        // 使用String的私有构造函数实现零拷贝
        char[] buf;
        if (value.length == count) {
            buf = value;
            value = EMPTY_CHARS;
        } else {
            buf = new char[count];
            System.arraycopy(value, 0, buf, 0, count);
        }
        reset();

        // 使用JIT友好的字符串创建方式
        return String.valueOf(buf);
    }

    public char[] toCharArray() {
        if (count == 0) return EMPTY_CHARS;

        char[] result = new char[count];
        System.arraycopy(value, 0, result, 0, count);
        return result;
    }

    private void ensureCapacity(int minCapacity) {
        if (minCapacity > value.length) {
            int newCapacity = calculateNewCapacity(minCapacity);
            char[] newValue = new char[newCapacity];
            System.arraycopy(value, 0, newValue, 0, count);

            if (threadLocalEnabled && value != threadBuffer.get()) {
                // 将旧缓冲区归还给池
                ThreadLocalBuffer.release(value);
            }

            value = newValue;
            reallocations++;
        }
    }

    private int calculateNewCapacity(int minCapacity) {
        int oldCapacity = value.length;
        int newCapacity = oldCapacity << 1;

        // 内存对齐优化 (64字节缓存行对齐)
        newCapacity = (newCapacity + 63) & ~63;

        if (newCapacity < minCapacity) {
            newCapacity = minCapacity;
            // 内存页对齐 (4KB)
            newCapacity = (newCapacity + 4095) & ~4095;
        }

        // 安全边界检查
        if (newCapacity < 0) {
            throw new OutOfMemoryError("Required length exceeds maximum capacity");
        }

        return newCapacity;
    }

    // 高效批量操作API
    public void forEachChar(IntConsumer action) {
        for (int i = 0; i < count; i++) {
            action.accept(value[i]);
        }
    }

    // 避免创建临时对象的查找方法
    public boolean contains(CharSequence sequence) {
        int seqLen = sequence.length();
        if (seqLen == 0) return true;
        if (seqLen > count) return false;

        char first = sequence.charAt(0);
        int max = count - seqLen;

        for (int i = 0; i <= max; i++) {
            if (value[i] == first) {
                int j = 1;
                for (; j < seqLen; j++) {
                    if (value[i + j] != sequence.charAt(j)) break;
                }
                if (j == seqLen) return true;
            }
        }
        return false;
    }

    // 线程局部缓存管理
    static class ThreadLocalBuffer {
        static final int STATIC_INIT_CAPACITY = 2048;
        static final int MAX_CACHE_SIZE = 10;

        private static final ThreadLocal<RingBuffer<char[]>> bufferCache =
                ThreadLocal.withInitial(RingBuffer::new);

        static char[] get() {
            char[] buf = bufferCache.get().poll();
            return buf != null ? buf : new char[STATIC_INIT_CAPACITY];
        }

        static void release(char[] buffer) {
            // 只缓存合理大小的缓冲区
            if (buffer.length <= STATIC_INIT_CAPACITY * 4) {
                RingBuffer<char[]> cache = bufferCache.get();
                if (!cache.isFull()) {
                    cache.offer(buffer);
                }
            }
        }

        // 高效环形缓存
        static class RingBuffer<T> {
            final Object[] buffer;
            int head, tail, size;

            RingBuffer() {
                buffer = new Object[MAX_CACHE_SIZE];
            }

            boolean isFull() {
                return size == MAX_CACHE_SIZE;
            }

            void offer(T item) {
                buffer[tail] = item;
                tail = (tail + 1) % MAX_CACHE_SIZE;
                if (size < MAX_CACHE_SIZE) size++;
                else head = (head + 1) % MAX_CACHE_SIZE; // 淘汰最旧的
            }

            @SuppressWarnings("unchecked")
            T poll() {
                if (size == 0) return null;
                T item = (T) buffer[head];
                buffer[head] = null;
                head = (head + 1) % MAX_CACHE_SIZE;
                size--;
                return item;
            }
        }
    }

    // 本地内存直接缓冲区 (可选)
    static class NativeMemoryBuffer {
        private static final VarHandle BYTE_HANDLE = MethodHandles.byteArrayViewVarHandle(
                char[].class, ByteOrder.nativeOrder());

        private long address;
        private long capacity;
        private long position;
        private char[] heapBuffer;

        NativeMemoryBuffer(long initialSize) {
            this.capacity = initialSize;
            this.heapBuffer = new char[(int)initialSize];
            this.address = 0; // 由JIT优化使用
        }

        void append(String str) {
            int strLen = str.length();
            if (position + strLen > capacity) {
                resize(position + strLen);
            }

            for (int i = 0; i < strLen; i++) {
                heapBuffer[(int)position++] = str.charAt(i);
            }
        }

        void free() {
            heapBuffer = null;
        }

        @Override
        public String toString() {
            return new String(heapBuffer, 0, (int)position);
        }

        private void resize(long minCapacity) {
            long newCapacity = capacity << 1;
            if (newCapacity < minCapacity) newCapacity = minCapacity;

            char[] newBuffer = new char[(int)newCapacity];
            System.arraycopy(heapBuffer, 0, newBuffer, 0, (int)position);
            heapBuffer = newBuffer;
            capacity = newCapacity;
        }
    }

    // 性能监控API
    public int getAllocationCount() {
        return allocations;
    }

    public int getReallocationCount() {
        return reallocations;
    }

    // 避免反射的静态工厂
    public static Supplier<FastStringBuilder> factory() {
        return FastStringBuilder::new;
    }

    // 结构化并发支持
    public static FastStringBuilder buildParallel(String... sequences) {
        if (sequences.length == 0) return new FastStringBuilder();
        if (sequences.length == 1) return new FastStringBuilder().append(sequences[0]);

        FastStringBuilder result = new FastStringBuilder();
        Thread[] workers = new Thread[sequences.length];

        for (int i = 0; i < sequences.length; i++) {
            final int index = i;
            workers[i] = Thread.ofVirtual().start(() -> {
                char[] segment = sequences[index].toString().toCharArray();
                synchronized(result) {
                    result.append(segment);
                }
            });
        }

        for (Thread worker : workers) {
            try {
                worker.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        return result;
    }
}